/**********************************************************************\

 Copyright 2012 Diggory Blake

 This file is part of klip-engine

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

\**********************************************************************/
#pragma once

#include <stdint.h>
#include <stddef.h>

struct kDataView;
struct kData;

class kDataBufferView;
class kDataBuffer;
class kStream;

#include "kbase.h"

struct kDataView {
public:
	const uint8_t* ptr;
	size_t size;

	inline kDataView() {
		ptr = 0;
		size = 0;
	}
	inline kDataView(const uint8_t* ptr, size_t size) {
		this->ptr = ptr;
		this->size = size;
	}
	template<size_t N> inline kDataView(const uint8_t (&ptr)[N]) {
		this->ptr = ptr;
		this->size = N;
	}
};

struct kData {
	uint8_t* ptr;
	size_t size;

	inline kData() {
		ptr = 0;
		size = 0;
	}
	inline kData(uint8_t* ptr, size_t size) {
		this->ptr = ptr;
		this->size = size;
	}
	inline operator kDataView() const {
		return kDataView(ptr, size);
	}
	template<size_t N> inline kData(uint8_t (&ptr)[N]) {
		this->ptr = ptr;
		this->size = N;
	}
};

class kDataBufferView : public kBase {
protected:
	kData _data;

	inline kDataBufferView() : _data() {
	}

public:
	kDataView getDataView() const {
		return _data;
	}
	inline const uint8_t* getPtr() const {
		return _data.ptr;
	}
	inline size_t getSize() const {
		return _data.size;
	}
	virtual ~kDataBufferView();
};

class kDataBuffer : public kDataBufferView {
public:
	kDataBuffer();
	kDataBuffer(size_t size);
	kDataBuffer(const kDataView& source);
	kDataBuffer(kStream* stream);
	virtual ~kDataBuffer();

	void resize(size_t size);
	void fill(uint8_t value = 0, size_t offset = 0, size_t length = -1) const;
	inline void resizeFill(size_t size, uint8_t value) {
		size_t oldsize = _data.size;
		resize(size);
		if (size > oldsize) {
			fill(value, oldsize, size - oldsize);
		}
	}
	void append(const kDataView& data);
	void replace(const kDataView& data);

	const kData& getData() const {
		return _data;
	}
	inline uint8_t* getPtr() const {
		return _data.ptr;
	}
};
